Chapter 10: Tibbles

Read R4ds Chapter 10: Tibbles, sections 1-3.

10.1: Introduction

Load the tidyverse package.

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.2     v purrr   0.3.4
v tibble  3.0.1     v dplyr   1.0.0
v tidyr   1.1.0     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

10.2: Creating tibbles

Enter your code chunks for Section 10.2 here.

Describe what each chunk code does.

Coercing dataframe iris to a tibble.

as_tibble(iris)

Creating a new tibble from individual vectors

tibble(
  x = 1:5, 
  y = 1, 
  z = x ^ 2 + y
)

Use non-syntactic names in tibble.

tb <- tibble(
  `:)` = "smile", 
  ` ` = "space",
  `2000` = "number"
)

make a transported tibble with tribble

tribble(
  ~x, ~y, ~z,
  #--|--|----
  "a", 2, 3.6,
  "b", 1, 8.5
)

10.3: Tibbles vs data.frame

Enter your code chunks for Section 10.2 here.

Describe what each chunk code does.

This code chunk shows tibbles print method that only shows first 10 rows, with the columns that fit on screen.

tibble(
  a = lubridate::now() + runif(1e3) * 86400,
  b = lubridate::today() + runif(1e3) * 30,
  c = 1:1e3,
  d = runif(1e3),
  e = sample(letters, 1e3, replace = TRUE)
)

This code chunk shows how to control the rows and columns shown from default in tibble.

nycflights13::flights %>% 
  print(n = 10, width = Inf)

This code chunk uses Rstudios built ikn data viewer.

nycflights13::flights %>% 
  View()

This code chunk assigns information to a variable df.

df <- tibble(
  x = runif(5),
  y = rnorm(5)
)

This code chunk manipulates df to extract a variable from it by name.

df$x

This code chunk does the same as above but a different method.

df[['x']]

This code chunk extracts by position.

df[[1]]

This code chunk shows the by name again but in a pipe with ‘.’ placeholder.

df %>% .$x

This code chunk is same as above but other method.

df %>% .[['x']]

10.4: Not required

Section 10.5 Questions

Answer the questions completely. Use code chunks, text, or both, as necessary.

1: How can you tell if an object is a tibble? (Hint: try printing mtcars, which is a regular data frame). Identify at least two ways to tell if an object is a tibble. Hint: What does as_tibble() do? What does class() do? What does str() do?

Tibble has a default printing setting to show only the first 10 rows unless instructed otherwise. Whereas a regular dataframe shows all rows.Tibble also does not change the type of inputs, the names of variables, and never creates row names.

2: Compare and contrast the following operations on a data.frame and equivalent tibble. What is different? Why might the default data frame behaviours cause you frustration?

This dataframe doesn’t use backticks (`) like tibble to refer to variables. This can cause issues with recognizing the variables.Tibble also enters each variable on a seperate line, rather than just one line fore all like dataframe.

Chapter 11: Importing data

Read R4ds Chapter 11: Data Import, sections 1, 2, and 5.

11.1 Introduction

Nothing to do here unless you took a break and need to reload tidyverse.

11.2 Getting started.

Do not run the first code chunk of this section, which begins with heights <- read_csv("data/heights.csv"). You do not have that data file so the code will not run.

Enter and run the remaining chunks in this section.

this code chunk runs read_csv, which reads comma delimited files. It prints out a column specification that gives the name and type of each column.

This code chunk shows how to use skip = n, to skip first n lines.

This code chunks shows how use comment = ‘#’ to skip a comment after “3”.

This cod chunk shows how to use col_names, when you dont use column names.

This code chunk shows how to give col_names a vector for the column names.

This code chunk shows how to use na for missing values.

11.2 Questions

1: What function would you use to read a file where fields were separated with “|”?

read_delim()

2: (This question is modified from the text.) Finish the two lines of read_delim code so that the first one would read a comma-separated file and the second would read a tab-separated file. You only need to worry about the delimiter. Do not worry about other arguments. Replace the dots in each line with the rest of your code.

Comma-separated

file <- read_delim("file.csv", delim = ",")

Tab-separated

file <- read_delim("file.csv", delim = " ")

3: What are the two most important arguments to read_fwf()? Why?

File, because it has to have data, and col_positions, because this is a needed argument to seperate the data.

4: Skip this question

5: Identify what is wrong with each of the following inline CSV files. What happens when you run the code?

Line 1 does not have a third column name, when ran the third column is not shown at all. Line 2 is missing a value in the first line of data and there is an extra in second, when ran the first row last column has na and the fourth value in second row of data is not shown. Line 3 is missing both values for first row of data and on for second row of data, when ran there is only one row of data and the second value is na. Line 4 needs to have the last row a an b in "" since they are not numbers and are letters for values instead, when ran the second row of data is shown as a and b. Line 5 is using ; as the seperator or it should be :, i am not sure which, without indicating so, when ran it shows a’b as the column title, and 1;3 as the data.

11.3 and 11.4: Not required

11.5: Writing to a file

Just read this section. You may find it helpful in the future to save a data file to your hard drive. It is basically the same format as reading a file, except that you must specify the data object to save, in addition to the path and file name.

11.6 Not required

Chapter 18: Pipes

Read R4ds Chapter 18: Pipes, sections 1-3.

Nothing to do otherwise for this chapter. Is this easy or what?

Note: Trying using pipes for all of the remaining examples. That will help you understand them.

Chapter 12: Tidy Data

Read R4ds Chapter 12: Tidy Data, sections 1-3, 7.

12.1 Introduction

Nothing to do here unless you took a break and need to reload the tidyverse.

12.2 Tidy data

Study Figure 12.1 and relate the diagram to the three rules listed just above them. Relate that back to the example I gave you in the notes. Bear this in mind as you make data tidy in the second part of this assignment.

You do not have to run any of the examples in this section.

12.3

Read and run the examples through section 12.3.1 (gathering), including the example with left_join(). We’ll cover joins later.

This code chunk tidy’s the table4a dataset,

Using pivot_longer() to tidy table4b.

This code chunk combines table4a and table4b.

left_join(tidy4a, tidy4b)
Joining, by = c("country", "year")

12.3 Questions

2: Why does this code fail? Fix it so it works.

That is all for Chapter 12. On to the last chapter.

Chapter 5: Data transformation

Read R4ds Chapter 5: Data Transformation, sections 1-4.

Time to get small.

5.1: Introduction

Load the necessary libraries. As usual, type the examples into and run the code chunks.

Load the libraries.

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.2     v purrr   0.3.4
v tibble  3.0.1     v dplyr   1.0.0
v tidyr   1.1.0     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

5.2: Filter rows with filter()

Study Figure 5.1 carefully. Once you learn the &, |, and ! logic, you will find them to be very powerful tools.

This chunk selects all flights on january 1st usinmg filter()

This code chunk saves the result above.

This code chunk saves and prints out results.

This code chunk shows the error of using = instead of ==.

filter(flights, month = 1)
Error: Problem with `filter()` input `..1`.
x Input `..1` is named.
i This usually means that you've used `=` instead of `==`.
i Did you mean `month == 1`?

This code chunk shows the errors of floatingpoint numbers.

sqrt(2) ^ 2 == 2
[1] FALSE

This code chunk has same purpose as above.

1 / 49 * 49 == 1
[1] FALSE

This code chunk shows how to use near().

near(sqrt(2) ^ 2,  2)
[1] TRUE

This chunk has same purpose as above.

near(1 / 49 * 49, 1)
[1] TRUE

This code chunk finds all flights departed in November or December.

This code chunk does the same as above but a shorter method, and assigns it to a name.

This code chunk shows fligths that weren’t delayed for more than 2 hours.

This chunk does sames as above but another ,ethod.

The next code chunk shows how a code involving na will be na.

NA > 5
[1] NA

This does same as above.

10 == NA
[1] NA

This also does same as above.

NA + 10
[1] NA

This does same as above.

NA / 2
[1] NA

This is same as above.

NA == NA
[1] NA

This code chunk is start of an example. x is mary’s age, which is unknown.

SAme as example above, y is John’s age, also unknown.

This is final part of above example to show why NA == NA is false.

y == x
[1] NA

This code chunk shows how to tell if a varaible is missing.

is.na(x)
[1] TRUE

This shows how to preserve missing values, the next three show this.

df <- tibble(x = c(1, NA, 3))

Example for above.

filter(df, x > 1)

Example for above as well.

filter(df, is.na(x) | x > 1)

5.2 Questions

1.1: Find all flights with a delay of 2 hours or more.

1.2: Flew to Houston (IAH or HOU)

1.3: Were operated by United (UA), American (AA), or Delta (DL).

1.4: Departed in summer (July, August, and September).

1.5: Arrived more than two hours late, but didn’t leave late.

1.6: Were delayed by at least an hour, but made up over 30 minutes in flight. This is a tricky one. Do your best.

1.7: Departed between midnight and 6am (inclusive)

2: Another useful dplyr filtering helper is between(). What does it do? Can you use it to simplify the code needed to answer the previous challenges?

between() is a shortcut for determining if values in a numeric vector fall in a specific range. Yes you could use this to make codes above simplier.

3: How many flights have a missing dep_time? What other variables are missing? What might these rows represent?

4: Why is NA ^ 0 not missing? Why is NA | TRUE not missing? Why is FALSE & NA not missing? Can you figure out the general rule? (NA * 0 is a tricky counterexample!)

‘NA ^ 0’ is not missing because any number ^ 0 is equal to one. ‘NA | TRUE’ is not missing because NA is going to show FALSE and considering all things are either TRUE or FALSE and this statement includes both it is not missing. ’ FALSE & NA’ is not missing because both equal FALSE.

Note: For some context, see this thread

5.3 Arrange with arrange()

This code chunk shows how to use arange() to change order of columns

This code chunk shows how to use desc() to re-order a column by descending order.

This code chunk shows missing values sorted at the end.

This is part of above.

Also, part of above.

5.3 Questions

1: How could you use arrange() to sort all missing values to the start? (Hint: use is.na()). Note: This one should still have the earliest departure dates after the NAs. Hint: What does desc() do?

2: Sort flights to find the most delayed flights. Find the flights that left earliest.

This question is asking for the flights that were most delayed (left latest after scheduled departure time) and least delayed (left ahead of scheduled time).

This code chunk shows Flights most delayed.

This code chunk shows flights least delayed.

3: Sort flights to find the fastest flights. Interpret fastest to mean shortest time in the air.

Optional challenge: fastest flight could refer to fastest air speed. Speed is measured in miles per hour but time is minutes. Arrange the data by fastest air speed.

4: Which flights travelled the longest? Which travelled the shortest?

Flights longest

traveled shortest

5.4 Select columns with select()

This code chunk shows how to only show certain columns from flights.

Does same as above.

This chunk shows how to not show columns from flights.

this code chunk shows how to rename variables.

This code chunk shows how to move variables to the start of the dataframe.

5.4 Questions

1: Brainstorm as many ways as possible to select dep_time, dep_delay, arr_time, and arr_delay from flights. Find at least three ways.

select(flights, ends_with('delay'), ends_with('time')
Error: unexpected symbol in:
"select(flights, ends_with('delay'), ends_with('time')
select"

2: What happens if you include the name of a variable multiple times in a select() call?

Nothing shows up when you run the code.

3: What does the one_of() function do? Why might it be helpful in conjunction with this vector?

vars <- c("year", "month", "day", "dep_delay", "arr_delay")

one_of() lets you select variables using a character vector of their names instead of putting their names into the select() call. If you are wanting this vector, you can use one_of() with some of variables to pull up the whole vector.

4: Does the result of running the following code surprise you? How do the select helpers deal with case by default? How can you change that default?

select(flights, contains(“TIME”))

LS0tDQp0aXRsZTogIkhXMDYgUGFydCAxOiBDb21wbGV0ZSB0aGUgc2VjdGlvbnMiDQphdXRob3I6ICJBbmRyZWEgV2luaW5nYXIiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KLSBDaGFuZ2UgInlvdXIgbmFtZSIgaW4gdGhlIFlBTUwgaGVhZGVyIGFib3ZlIHRvIHlvdXIgbmFtZS4NCg0KLSBBcyB1c3VhbCwgZW50ZXIgdGhlIGV4YW1wbGVzIGluIGNvZGUgY2h1bmtzIGFuZCBydW4gdGhlbSwgdW5sZXNzIHRvbGQgb3RoZXJ3aXNlLg0KDQojIyBDaGFwdGVyIDEwOiBUaWJibGVzDQoNClJlYWQgW1I0ZHMgQ2hhcHRlciAxMDogVGliYmxlc10oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei90aWJibGVzLmh0bWwpLCBzZWN0aW9ucyAxLTMuDQoNCiMjIyAxMC4xOiBJbnRyb2R1Y3Rpb24NCg0KTG9hZCB0aGUgdGlkeXZlcnNlIHBhY2thZ2UuIA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCg0KIyMjIDEwLjI6IENyZWF0aW5nIHRpYmJsZXMNCg0KRW50ZXIgeW91ciBjb2RlIGNodW5rcyBmb3IgU2VjdGlvbiAxMC4yIGhlcmUuDQoNCkRlc2NyaWJlIHdoYXQgZWFjaCBjaHVuayBjb2RlIGRvZXMuIA0KDQpDb2VyY2luZyBkYXRhZnJhbWUgaXJpcyB0byBhIHRpYmJsZS4NCg0KYGBge3J9DQphc190aWJibGUoaXJpcykNCmBgYA0KDQpDcmVhdGluZyBhIG5ldyB0aWJibGUgZnJvbSBpbmRpdmlkdWFsIHZlY3RvcnMNCg0KYGBge3J9DQp0aWJibGUoDQogIHggPSAxOjUsIA0KICB5ID0gMSwgDQogIHogPSB4IF4gMiArIHkNCikNCmBgYA0KDQpVc2Ugbm9uLXN5bnRhY3RpYyBuYW1lcyBpbiB0aWJibGUuDQoNCmBgYHtyfQ0KdGIgPC0gdGliYmxlKA0KICBgOilgID0gInNtaWxlIiwgDQogIGAgYCA9ICJzcGFjZSIsDQogIGAyMDAwYCA9ICJudW1iZXIiDQopDQpgYGANCg0KbWFrZSBhIHRyYW5zcG9ydGVkIHRpYmJsZSB3aXRoIHRyaWJibGUNCg0KYGBge3J9DQp0cmliYmxlKA0KICB+eCwgfnksIH56LA0KICAjLS18LS18LS0tLQ0KICAiYSIsIDIsIDMuNiwNCiAgImIiLCAxLCA4LjUNCikNCmBgYA0KDQojIyMgMTAuMzogVGliYmxlcyB2cyBkYXRhLmZyYW1lDQoNCkVudGVyIHlvdXIgY29kZSBjaHVua3MgZm9yIFNlY3Rpb24gMTAuMiBoZXJlLg0KDQpEZXNjcmliZSB3aGF0IGVhY2ggY2h1bmsgY29kZSBkb2VzLiANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIHRpYmJsZXMgcHJpbnQgbWV0aG9kIHRoYXQgb25seSBzaG93cyBmaXJzdCAxMCByb3dzLCB3aXRoIHRoZSBjb2x1bW5zIHRoYXQgZml0IG9uIHNjcmVlbi4NCg0KYGBge3J9DQp0aWJibGUoDQogIGEgPSBsdWJyaWRhdGU6Om5vdygpICsgcnVuaWYoMWUzKSAqIDg2NDAwLA0KICBiID0gbHVicmlkYXRlOjp0b2RheSgpICsgcnVuaWYoMWUzKSAqIDMwLA0KICBjID0gMToxZTMsDQogIGQgPSBydW5pZigxZTMpLA0KICBlID0gc2FtcGxlKGxldHRlcnMsIDFlMywgcmVwbGFjZSA9IFRSVUUpDQopDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIGhvdyB0byBjb250cm9sIHRoZSByb3dzIGFuZCBjb2x1bW5zIHNob3duIGZyb20gZGVmYXVsdCBpbiB0aWJibGUuDQoNCmBgYHtyfQ0KbnljZmxpZ2h0czEzOjpmbGlnaHRzICU+JSANCiAgcHJpbnQobiA9IDEwLCB3aWR0aCA9IEluZikNCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgdXNlcyBSc3R1ZGlvcyBidWlsdCBpa24gZGF0YSB2aWV3ZXIuDQoNCmBgYHtyfQ0KbnljZmxpZ2h0czEzOjpmbGlnaHRzICU+JSANCiAgVmlldygpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIGFzc2lnbnMgaW5mb3JtYXRpb24gdG8gYSB2YXJpYWJsZSBkZi4NCg0KYGBge3J9DQpkZiA8LSB0aWJibGUoDQogIHggPSBydW5pZig1KSwNCiAgeSA9IHJub3JtKDUpDQopDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIG1hbmlwdWxhdGVzIGRmIHRvIGV4dHJhY3QgYSB2YXJpYWJsZSBmcm9tIGl0IGJ5IG5hbWUuDQoNCmBgYHtyfQ0KZGYkeA0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBkb2VzIHRoZSBzYW1lIGFzIGFib3ZlIGJ1dCBhIGRpZmZlcmVudCBtZXRob2QuDQoNCmBgYHtyfQ0KZGZbWyd4J11dDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIGV4dHJhY3RzIGJ5IHBvc2l0aW9uLg0KDQpgYGB7cn0NCmRmW1sxXV0NCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgdGhlIGJ5IG5hbWUgYWdhaW4gYnV0IGluIGEgcGlwZSB3aXRoICcuJyBwbGFjZWhvbGRlci4NCg0KYGBge3J9DQpkZiAlPiUgLiR4DQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIGlzIHNhbWUgYXMgYWJvdmUgYnV0IG90aGVyIG1ldGhvZC4NCg0KYGBge3J9DQpkZiAlPiUgLltbJ3gnXV0NCmBgYA0KDQojIyMgMTAuNDogTm90IHJlcXVpcmVkDQoNCiMjIyMgU2VjdGlvbiAxMC41IFF1ZXN0aW9ucw0KDQpBbnN3ZXIgdGhlIHF1ZXN0aW9ucyAqY29tcGxldGVseS4qIFVzZSBjb2RlIGNodW5rcywgdGV4dCwgb3IgYm90aCwgYXMgbmVjZXNzYXJ5Lg0KDQoqKjE6KiogSG93IGNhbiB5b3UgdGVsbCBpZiBhbiBvYmplY3QgaXMgYSB0aWJibGU/IChIaW50OiB0cnkgcHJpbnRpbmcgYG10Y2Fyc2AsIHdoaWNoIGlzIGEgcmVndWxhciBkYXRhIGZyYW1lKS4gSWRlbnRpZnkgYXQgbGVhc3QgdHdvIHdheXMgdG8gdGVsbCBpZiBhbiBvYmplY3QgaXMgYSB0aWJibGUuICpIaW50OiogV2hhdCBkb2VzIGBhc190aWJibGUoKWAgZG8/IFdoYXQgZG9lcyBgY2xhc3MoKWAgZG8/IFdoYXQgZG9lcyBgc3RyKClgIGRvPw0KDQpUaWJibGUgaGFzIGEgZGVmYXVsdCBwcmludGluZyBzZXR0aW5nIHRvIHNob3cgb25seSB0aGUgZmlyc3QgMTAgcm93cyB1bmxlc3MgaW5zdHJ1Y3RlZCBvdGhlcndpc2UuIFdoZXJlYXMgYSByZWd1bGFyIGRhdGFmcmFtZSBzaG93cyBhbGwgcm93cy5UaWJibGUgYWxzbyBkb2VzIG5vdCBjaGFuZ2UgdGhlIHR5cGUgb2YgaW5wdXRzLCB0aGUgbmFtZXMgb2YgdmFyaWFibGVzLCBhbmQgbmV2ZXIgY3JlYXRlcyByb3cgbmFtZXMuIA0KDQoqKjI6KiogQ29tcGFyZSBhbmQgY29udHJhc3QgdGhlIGZvbGxvd2luZyBvcGVyYXRpb25zIG9uIGEgZGF0YS5mcmFtZSBhbmQgZXF1aXZhbGVudCB0aWJibGUuIFdoYXQgaXMgZGlmZmVyZW50PyBXaHkgbWlnaHQgdGhlIGRlZmF1bHQgZGF0YSBmcmFtZSBiZWhhdmlvdXJzIGNhdXNlIHlvdSBmcnVzdHJhdGlvbj8NCg0KYGBge3J9DQpkZiA8LSBkYXRhLmZyYW1lKGFiYyA9IDEsIHh5eiA9ICJhIikNCmRmJHgNCmRmWywgInh5eiJdDQpkZlssIGMoImFiYyIsICJ4eXoiKV0NCmBgYA0KDQpUaGlzIGRhdGFmcmFtZSBkb2Vzbid0IHVzZSBiYWNrdGlja3MgKGApIGxpa2UgdGliYmxlIHRvIHJlZmVyIHRvIHZhcmlhYmxlcy4gVGhpcyBjYW4gY2F1c2UgaXNzdWVzIHdpdGggcmVjb2duaXppbmcgdGhlIHZhcmlhYmxlcy5UaWJibGUgYWxzbyBlbnRlcnMgZWFjaCB2YXJpYWJsZSBvbiBhIHNlcGVyYXRlIGxpbmUsIHJhdGhlciB0aGFuIGp1c3Qgb25lIGxpbmUgZm9yZSBhbGwgbGlrZSBkYXRhZnJhbWUuIA0KDQojIyBDaGFwdGVyIDExOiBJbXBvcnRpbmcgZGF0YQ0KDQpSZWFkIFtSNGRzIENoYXB0ZXIgMTE6IERhdGEgSW1wb3J0XShodHRwczovL3I0ZHMuaGFkLmNvLm56L2RhdGEtaW1wb3J0Lmh0bWwpLCBzZWN0aW9ucyAxLCAyLCBhbmQgNS4NCg0KIyMjIDExLjEgSW50cm9kdWN0aW9uDQoNCk5vdGhpbmcgdG8gZG8gaGVyZSB1bmxlc3MgeW91IHRvb2sgYSBicmVhayBhbmQgbmVlZCB0byByZWxvYWQgYHRpZHl2ZXJzZWAuDQoNCiMjIyAxMS4yIEdldHRpbmcgc3RhcnRlZC4NCg0KRG8gKm5vdCogcnVuIHRoZSBmaXJzdCBjb2RlIGNodW5rIG9mIHRoaXMgc2VjdGlvbiwgd2hpY2ggYmVnaW5zIHdpdGggYGhlaWdodHMgPC0gcmVhZF9jc3YoImRhdGEvaGVpZ2h0cy5jc3YiKWAuIFlvdSBkbyBub3QgaGF2ZSB0aGF0IGRhdGEgZmlsZSBzbyB0aGUgY29kZSB3aWxsIG5vdCBydW4uDQoNCkVudGVyIGFuZCBydW4gdGhlIHJlbWFpbmluZyBjaHVua3MgaW4gdGhpcyBzZWN0aW9uLg0KDQp0aGlzIGNvZGUgY2h1bmsgcnVucyByZWFkX2Nzdiwgd2hpY2ggcmVhZHMgY29tbWEgZGVsaW1pdGVkIGZpbGVzLiBJdCBwcmludHMgb3V0IGEgY29sdW1uIHNwZWNpZmljYXRpb24gdGhhdCBnaXZlcyB0aGUgbmFtZSBhbmQgdHlwZSBvZiBlYWNoIGNvbHVtbi4gDQoNCmBgYHtyfQ0KcmVhZF9jc3YoImEsYixjDQoxLDIsMw0KNCw1LDYiKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzaG93cyBob3cgdG8gdXNlIHNraXAgPSBuLCB0byBza2lwIGZpcnN0IG4gbGluZXMuDQoNCmBgYHtyfQ0KcmVhZF9jc3YoIlRoZSBmaXJzdCBsaW5lIG9mIG1ldGFkYXRhDQogIFRoZSBzZWNvbmQgbGluZSBvZiBtZXRhZGF0YQ0KICB4LHkseg0KICAxLDIsMyIsIHNraXAgPSAyKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVua3Mgc2hvd3MgaG93IHVzZSBjb21tZW50ID0gJyMnIHRvIHNraXAgYSBjb21tZW50IGFmdGVyICIzIi4NCg0KYGBge3J9DQpyZWFkX2NzdigiIyBBIGNvbW1lbnQgSSB3YW50IHRvIHNraXANCiAgeCx5LHoNCiAgMSwyLDMiLCBjb21tZW50ID0gIiMiKQ0KYGBgDQoNClRoaXMgY29kIGNodW5rIHNob3dzIGhvdyB0byB1c2UgY29sX25hbWVzLCB3aGVuIHlvdSBkb250IHVzZSBjb2x1bW4gbmFtZXMuDQoNCmBgYHtyfQ0KcmVhZF9jc3YoIjEsMiwzXG40LDUsNiIsIGNvbF9uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzaG93cyBob3cgdG8gZ2l2ZSBjb2xfbmFtZXMgYSB2ZWN0b3IgZm9yIHRoZSBjb2x1bW4gbmFtZXMuDQoNCmBgYHtyfQ0KcmVhZF9jc3YoIjEsMiwzXG40LDUsNiIsIGNvbF9uYW1lcyA9IGMoIngiLCAieSIsICJ6IikpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIGhvdyB0byB1c2UgbmEgZm9yIG1pc3NpbmcgdmFsdWVzLg0KDQpgYGB7cn0NCnJlYWRfY3N2KCJhLGIsY1xuMSwyLC4iLCBuYSA9ICIuIikNCmBgYA0KDQojIyMjIDExLjIgUXVlc3Rpb25zDQoNCioqMToqKiBXaGF0IGZ1bmN0aW9uIHdvdWxkIHlvdSB1c2UgdG8gcmVhZCBhIGZpbGUgd2hlcmUgZmllbGRzIHdlcmUgc2VwYXJhdGVkIHdpdGggInwiPw0KDQpyZWFkX2RlbGltKCkNCg0KKioyOioqIChUaGlzIHF1ZXN0aW9uIGlzIG1vZGlmaWVkIGZyb20gdGhlIHRleHQuKSBGaW5pc2ggdGhlIHR3byBsaW5lcyBvZiBgcmVhZF9kZWxpbWAgY29kZSBzbyB0aGF0IHRoZSBmaXJzdCBvbmUgd291bGQgcmVhZCBhIGNvbW1hLXNlcGFyYXRlZCBmaWxlIGFuZCB0aGUgc2Vjb25kIHdvdWxkIHJlYWQgYSB0YWItc2VwYXJhdGVkIGZpbGUuIFlvdSBvbmx5IG5lZWQgdG8gd29ycnkgYWJvdXQgdGhlIGRlbGltaXRlci4gRG8gbm90IHdvcnJ5IGFib3V0IG90aGVyIGFyZ3VtZW50cy4gUmVwbGFjZSB0aGUgZG90cyBpbiBlYWNoIGxpbmUgd2l0aCB0aGUgcmVzdCBvZiB5b3VyIGNvZGUuIA0KDQojIENvbW1hLXNlcGFyYXRlZA0KYGZpbGUgPC0gcmVhZF9kZWxpbSgiZmlsZS5jc3YiLCBkZWxpbSA9ICIsIilgDQoNCiMgVGFiLXNlcGFyYXRlZA0KYGZpbGUgPC0gcmVhZF9kZWxpbSgiZmlsZS5jc3YiLCBkZWxpbSA9ICIgICAiKWANCg0KDQoqKjM6KiogV2hhdCBhcmUgdGhlIHR3byBtb3N0IGltcG9ydGFudCBhcmd1bWVudHMgdG8gYHJlYWRfZndmKClgPyBXaHk/DQoNCkZpbGUsIGJlY2F1c2UgaXQgaGFzIHRvIGhhdmUgZGF0YSwgYW5kIGNvbF9wb3NpdGlvbnMsIGJlY2F1c2UgdGhpcyBpcyBhIG5lZWRlZCBhcmd1bWVudCB0byBzZXBlcmF0ZSB0aGUgZGF0YS4NCg0KKio0OioqIFNraXAgdGhpcyBxdWVzdGlvbg0KDQoNCioqNTogKiogSWRlbnRpZnkgd2hhdCBpcyB3cm9uZyB3aXRoIGVhY2ggb2YgdGhlIGZvbGxvd2luZyBpbmxpbmUgQ1NWIGZpbGVzLiBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgcnVuIHRoZSBjb2RlPw0KDQpgYGB7cn0NCnJlYWRfY3N2KCJhLGJcbjEsMiwzXG40LDUsNiIpDQpyZWFkX2NzdigiYSxiLGNcbjEsMlxuMSwyLDMsNCIpDQpyZWFkX2NzdigiYSxiXG5cIjEiKQ0KcmVhZF9jc3YoImEsYlxuMSwyXG5hLGIiKQ0KcmVhZF9jc3YoImE7YlxuMTszIikNCmBgYA0KDQpMaW5lIDEgZG9lcyBub3QgaGF2ZSBhIHRoaXJkIGNvbHVtbiBuYW1lLCB3aGVuIHJhbiB0aGUgdGhpcmQgY29sdW1uIGlzIG5vdCBzaG93biBhdCBhbGwuIExpbmUgMiBpcyBtaXNzaW5nIGEgdmFsdWUgaW4gdGhlIGZpcnN0IGxpbmUgb2YgZGF0YSBhbmQgdGhlcmUgaXMgYW4gZXh0cmEgaW4gc2Vjb25kLCB3aGVuIHJhbiB0aGUgZmlyc3Qgcm93IGxhc3QgY29sdW1uIGhhcyBuYSBhbmQgdGhlIGZvdXJ0aCB2YWx1ZSBpbiBzZWNvbmQgcm93IG9mIGRhdGEgaXMgbm90IHNob3duLiBMaW5lIDMgaXMgbWlzc2luZyBib3RoIHZhbHVlcyBmb3IgZmlyc3Qgcm93IG9mIGRhdGEgYW5kIG9uIGZvciBzZWNvbmQgcm93IG9mIGRhdGEsIHdoZW4gcmFuIHRoZXJlIGlzIG9ubHkgb25lIHJvdyBvZiBkYXRhIGFuZCB0aGUgc2Vjb25kIHZhbHVlIGlzIG5hLiBMaW5lIDQgbmVlZHMgdG8gaGF2ZSB0aGUgbGFzdCByb3cgYSBhbiBiIGluICIiIHNpbmNlIHRoZXkgYXJlIG5vdCBudW1iZXJzIGFuZCBhcmUgbGV0dGVycyBmb3IgdmFsdWVzIGluc3RlYWQsIHdoZW4gcmFuIHRoZSBzZWNvbmQgcm93IG9mIGRhdGEgaXMgc2hvd24gYXMgYSBhbmQgYi4gTGluZSA1IGlzIHVzaW5nIDsgYXMgdGhlIHNlcGVyYXRvciBvciBpdCBzaG91bGQgYmUgOiwgaSBhbSBub3Qgc3VyZSB3aGljaCwgd2l0aG91dCBpbmRpY2F0aW5nIHNvLCB3aGVuIHJhbiBpdCBzaG93cyBhJ2IgYXMgdGhlIGNvbHVtbiB0aXRsZSwgYW5kIDE7MyBhcyB0aGUgZGF0YS4NCg0KIyMjIDExLjMgYW5kIDExLjQ6IE5vdCByZXF1aXJlZA0KDQojIyMgMTEuNTogV3JpdGluZyB0byBhIGZpbGUNCg0KSnVzdCByZWFkIHRoaXMgc2VjdGlvbi4gWW91IG1heSBmaW5kIGl0IGhlbHBmdWwgaW4gdGhlIGZ1dHVyZSB0byBzYXZlIGEgZGF0YSBmaWxlIHRvIHlvdXIgaGFyZCBkcml2ZS4gSXQgaXMgYmFzaWNhbGx5IHRoZSBzYW1lIGZvcm1hdCBhcyByZWFkaW5nIGEgZmlsZSwgZXhjZXB0IHRoYXQgeW91IG11c3Qgc3BlY2lmeSB0aGUgZGF0YSBvYmplY3QgdG8gc2F2ZSwgaW4gYWRkaXRpb24gdG8gdGhlIHBhdGggYW5kIGZpbGUgbmFtZS4NCg0KIyMjIDExLjYgTm90IHJlcXVpcmVkDQoNCiMjIENoYXB0ZXIgMTg6IFBpcGVzDQoNClJlYWQgW1I0ZHMgQ2hhcHRlciAxODogUGlwZXNdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovcGlwZXMuaHRtbCksIHNlY3Rpb25zIDEtMy4NCg0KTm90aGluZyB0byBkbyBvdGhlcndpc2UgZm9yIHRoaXMgY2hhcHRlci4gSXMgdGhpcyBlYXN5IG9yIHdoYXQ/DQoNCioqTm90ZToqKiBUcnlpbmcgdXNpbmcgcGlwZXMgZm9yIGFsbCBvZiB0aGUgcmVtYWluaW5nIGV4YW1wbGVzLiBUaGF0IHdpbGwgaGVscCB5b3UgdW5kZXJzdGFuZCB0aGVtLg0KDQojIyBDaGFwdGVyIDEyOiBUaWR5IERhdGENCg0KUmVhZCBbUjRkcyBDaGFwdGVyIDEyOiBUaWR5IERhdGFdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovdGlkeS1kYXRhLmh0bWwpLCBzZWN0aW9ucyAxLTMsIDcuIA0KDQojIyMgMTIuMSBJbnRyb2R1Y3Rpb24NCg0KTm90aGluZyB0byBkbyBoZXJlIHVubGVzcyB5b3UgdG9vayBhIGJyZWFrIGFuZCBuZWVkIHRvIHJlbG9hZCB0aGUgYHRpZHl2ZXJzZS5gDQoNCiMjIyAxMi4yIFRpZHkgZGF0YQ0KDQpTdHVkeSBGaWd1cmUgMTIuMSBhbmQgcmVsYXRlIHRoZSBkaWFncmFtIHRvIHRoZSB0aHJlZSBydWxlcyBsaXN0ZWQganVzdCBhYm92ZSB0aGVtLiBSZWxhdGUgdGhhdCBiYWNrIHRvIHRoZSBleGFtcGxlIEkgZ2F2ZSB5b3UgaW4gdGhlIG5vdGVzLiBCZWFyIHRoaXMgaW4gbWluZCBhcyB5b3UgbWFrZSBkYXRhIHRpZHkgaW4gdGhlIHNlY29uZCBwYXJ0IG9mIHRoaXMgYXNzaWdubWVudC4NCg0KWW91IGRvIG5vdCBoYXZlIHRvIHJ1biBhbnkgb2YgdGhlIGV4YW1wbGVzIGluIHRoaXMgc2VjdGlvbi4NCg0KIyMjIDEyLjMNCg0KUmVhZCBhbmQgcnVuIHRoZSBleGFtcGxlcyB0aHJvdWdoIHNlY3Rpb24gMTIuMy4xIChnYXRoZXJpbmcpLCBpbmNsdWRpbmcgdGhlIGV4YW1wbGUgd2l0aCBgbGVmdF9qb2luKClgLiBXZSdsbCBjb3ZlciBqb2lucyBsYXRlci4NCg0KVGhpcyBjb2RlIGNodW5rIHRpZHkncyB0aGUgdGFibGU0YSBkYXRhc2V0LA0KDQpgYGB7cn0NCnRhYmxlNGEgJT4lIA0KICBwaXZvdF9sb25nZXIoYyhgMTk5OWAsIGAyMDAwYCksIG5hbWVzX3RvID0gInllYXIiLCB2YWx1ZXNfdG8gPSAiY2FzZXMiKQ0KYGBgDQoNClVzaW5nIHBpdm90X2xvbmdlcigpIHRvIHRpZHkgdGFibGU0Yi4NCg0KYGBge3J9DQp0YWJsZTRiICU+JSANCiAgcGl2b3RfbG9uZ2VyKGMoYDE5OTlgLCBgMjAwMGApLCBuYW1lc190byA9ICJ5ZWFyIiwgdmFsdWVzX3RvID0gInBvcHVsYXRpb24iKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBjb21iaW5lcyB0YWJsZTRhIGFuZCB0YWJsZTRiLg0KDQpgYGB7cn0NCnRpZHk0YSA8LSB0YWJsZTRhICU+JSANCiAgcGl2b3RfbG9uZ2VyKGMoYDE5OTlgLCBgMjAwMGApLCBuYW1lc190byA9ICJ5ZWFyIiwgdmFsdWVzX3RvID0gImNhc2VzIikNCnRpZHk0YiA8LSB0YWJsZTRiICU+JSANCiAgcGl2b3RfbG9uZ2VyKGMoYDE5OTlgLCBgMjAwMGApLCBuYW1lc190byA9ICJ5ZWFyIiwgdmFsdWVzX3RvID0gInBvcHVsYXRpb24iKQ0KbGVmdF9qb2luKHRpZHk0YSwgdGlkeTRiKQ0KYGBgDQoNCiMjIyMgMTIuMyBRdWVzdGlvbnMNCg0KKioyOioqIFdoeSBkb2VzIHRoaXMgY29kZSBmYWlsPyBGaXggaXQgc28gaXQgd29ya3MuDQoNCmBgYHtyfQ0KdGFibGU0YSAlPiUgDQogIHBpdm90X2xvbmdlcihjKGAxOTk5YCwgYDIwMDBgKSwgbmFtZXNfdG8gPSAieWVhciIsIHZhbHVlc190byA9ICJjYXNlcyIpDQojPiBFcnJvciBpbiBpbmRzX2NvbWJpbmUoLnZhcnMsIGluZF9saXN0KTogUG9zaXRpb24gbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIG4NCmBgYA0KDQpUaGF0IGlzIGFsbCBmb3IgQ2hhcHRlciAxMi4gT24gdG8gdGhlIGxhc3QgY2hhcHRlci4NCg0KDQojIyBDaGFwdGVyIDU6IERhdGEgdHJhbnNmb3JtYXRpb24NCg0KUmVhZCBbUjRkcyBDaGFwdGVyIDU6IERhdGEgVHJhbnNmb3JtYXRpb25dKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovdHJhbnNmb3JtLmh0bWwpLCBzZWN0aW9ucyAxLTQuDQoNClRpbWUgdG8gW2dldCBzbWFsbC5dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9R09yZHpDSG5wdzQpIA0KDQojIyMgNS4xOiBJbnRyb2R1Y3Rpb24NCg0KTG9hZCB0aGUgbmVjZXNzYXJ5IGxpYnJhcmllcy4gQXMgdXN1YWwsIHR5cGUgdGhlIGV4YW1wbGVzIGludG8gYW5kIHJ1biB0aGUgY29kZSBjaHVua3MuDQoNCkxvYWQgdGhlIGxpYnJhcmllcy4NCg0KYGBge3J9DQpsaWJyYXJ5KG55Y2ZsaWdodHMxMykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCg0KIyMjIDUuMjogRmlsdGVyIHJvd3Mgd2l0aCBgZmlsdGVyKClgDQoNClN0dWR5IEZpZ3VyZSA1LjEgY2FyZWZ1bGx5LiBPbmNlIHlvdSBsZWFybiB0aGUgYCZgLCBgfGAsIGFuZCBgIWAgbG9naWMsIHlvdSB3aWxsIGZpbmQgdGhlbSB0byBiZSB2ZXJ5IHBvd2VyZnVsIHRvb2xzLg0KDQpUaGlzIGNodW5rIHNlbGVjdHMgYWxsIGZsaWdodHMgb24gamFudWFyeSAxc3QgdXNpbm1nIGZpbHRlcigpDQoNCmBgYHtyfQ0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDEsIGRheSA9PSAxKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzYXZlcyB0aGUgcmVzdWx0IGFib3ZlLg0KDQpgYGB7cn0NCmphbjEgPC0gZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDEsIGRheSA9PSAxKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzYXZlcyBhbmQgcHJpbnRzIG91dCByZXN1bHRzLg0KDQpgYGB7cn0NCihkZWMyNSA8LSBmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMTIsIGRheSA9PSAyNSkpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIHRoZSBlcnJvciBvZiB1c2luZyA9IGluc3RlYWQgb2YgPT0uDQoNCmBgYHtyfQ0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID0gMSkNCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgdGhlIGVycm9ycyBvZiBmbG9hdGluZ3BvaW50IG51bWJlcnMuDQoNCmBgYHtyfQ0Kc3FydCgyKSBeIDIgPT0gMg0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBoYXMgc2FtZSBwdXJwb3NlIGFzIGFib3ZlLg0KDQpgYGB7cn0NCjEgLyA0OSAqIDQ5ID09IDENCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgaG93IHRvIHVzZSBuZWFyKCkuDQoNCmBgYHtyfQ0KbmVhcihzcXJ0KDIpIF4gMiwgIDIpDQpgYGANCg0KVGhpcyBjaHVuayBoYXMgc2FtZSBwdXJwb3NlIGFzIGFib3ZlLg0KDQpgYGB7cn0NCm5lYXIoMSAvIDQ5ICogNDksIDEpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIGZpbmRzIGFsbCBmbGlnaHRzIGRlcGFydGVkIGluIE5vdmVtYmVyIG9yIERlY2VtYmVyLg0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBtb250aCA9PSAxMSB8IG1vbnRoID09IDEyKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBkb2VzIHRoZSBzYW1lIGFzIGFib3ZlIGJ1dCBhIHNob3J0ZXIgbWV0aG9kLCBhbmQgYXNzaWducyBpdCB0byBhIG5hbWUuDQoNCmBgYHtyfQ0Kbm92X2RlYyA8LSBmaWx0ZXIoZmxpZ2h0cywgbW9udGggJWluJSBjKDExLCAxMikpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIGZsaWd0aHMgdGhhdCB3ZXJlbid0IGRlbGF5ZWQgZm9yIG1vcmUgdGhhbiAyIGhvdXJzLg0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCAhKGFycl9kZWxheSA+IDEyMCB8IGRlcF9kZWxheSA+IDEyMCkpDQpgYGANCg0KVGhpcyBjaHVuayBkb2VzIHNhbWVzIGFzIGFib3ZlIGJ1dCBhbm90aGVyICxldGhvZC4NCg0KYGBge3J9DQpmaWx0ZXIoZmxpZ2h0cywgYXJyX2RlbGF5IDw9IDEyMCwgZGVwX2RlbGF5IDw9IDEyMCkNCmBgYA0KDQpUaGUgbmV4dCBjb2RlIGNodW5rIHNob3dzIGhvdyBhIGNvZGUgaW52b2x2aW5nIG5hIHdpbGwgYmUgbmEuDQoNCmBgYHtyfQ0KTkEgPiA1DQpgYGANCg0KVGhpcyBkb2VzIHNhbWUgYXMgYWJvdmUuDQoNCmBgYHtyfQ0KMTAgPT0gTkENCmBgYA0KDQpUaGlzIGFsc28gZG9lcyBzYW1lIGFzIGFib3ZlLg0KDQpgYGB7cn0NCk5BICsgMTANCmBgYA0KDQpUaGlzIGRvZXMgc2FtZSBhcyBhYm92ZS4NCg0KYGBge3J9DQpOQSAvIDINCmBgYA0KDQpUaGlzIGlzIHNhbWUgYXMgYWJvdmUuDQoNCmBgYHtyfQ0KTkEgPT0gTkENCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgaXMgc3RhcnQgb2YgYW4gZXhhbXBsZS4geCBpcyBtYXJ5J3MgYWdlLCB3aGljaCBpcyB1bmtub3duLg0KDQpgYGB7cn0NCnggPC0gTkENCmBgYA0KDQpTQW1lIGFzIGV4YW1wbGUgYWJvdmUsIHkgaXMgSm9obidzIGFnZSwgYWxzbyB1bmtub3duLg0KDQpgYGB7cn0NCnkgPC0gTkENCmBgYA0KDQpUaGlzIGlzIGZpbmFsIHBhcnQgb2YgYWJvdmUgZXhhbXBsZSB0byBzaG93IHdoeSBOQSA9PSBOQSBpcyBmYWxzZS4NCg0KYGBge3J9DQp5ID09IHgNCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgaG93IHRvIHRlbGwgaWYgYSB2YXJhaWJsZSBpcyBtaXNzaW5nLg0KDQpgYGB7cn0NCmlzLm5hKHgpDQpgYGANCg0KVGhpcyBzaG93cyBob3cgdG8gcHJlc2VydmUgbWlzc2luZyB2YWx1ZXMsIHRoZSBuZXh0IHRocmVlIHNob3cgdGhpcy4NCg0KYGBge3J9DQpkZiA8LSB0aWJibGUoeCA9IGMoMSwgTkEsIDMpKQ0KYGBgDQoNCkV4YW1wbGUgZm9yIGFib3ZlLg0KDQpgYGB7cn0NCmZpbHRlcihkZiwgeCA+IDEpDQpgYGANCg0KRXhhbXBsZSBmb3IgYWJvdmUgYXMgd2VsbC4NCg0KYGBge3J9DQpmaWx0ZXIoZGYsIGlzLm5hKHgpIHwgeCA+IDEpDQpgYGANCg0KDQojIyMjIDUuMiBRdWVzdGlvbnMNCg0KKioxLjE6KiogRmluZCBhbGwgZmxpZ2h0cyB3aXRoIGEgZGVsYXkgb2YgMiBob3VycyBvciBtb3JlLg0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBhcnJfZGVsYXkgPj0gMTIwLCBkZXBfZGVsYXkgPj0gMTIwKQ0KYGBgDQoNCg0KKioxLjI6KiogRmxldyB0byBIb3VzdG9uIChJQUggb3IgSE9VKQ0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBkZXN0ID09ICdJQUgnIHwgZGVzdCA9PSAnSE9VJykNCmBgYA0KDQoqKjEuMzoqKiBXZXJlIG9wZXJhdGVkIGJ5IFVuaXRlZCAoVUEpLCBBbWVyaWNhbiAoQUEpLCBvciBEZWx0YSAoREwpLg0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBjYXJyaWVyID09ICdVQScgfCBjYXJyaWVyID09ICdBQScgfCBjYXJyaWVyID09ICdETCcpDQpgYGANCg0KKioxLjQ6KiogRGVwYXJ0ZWQgaW4gc3VtbWVyIChKdWx5LCBBdWd1c3QsIGFuZCBTZXB0ZW1iZXIpLg0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBtb250aCAgPT0gNyB8IG1vbnRoID09IDggfCBtb250aCA9PSA5KQ0KYGBgDQoNCioqMS41OioqIEFycml2ZWQgbW9yZSB0aGFuIHR3byBob3VycyBsYXRlLCBidXQgZGlkbuKAmXQgbGVhdmUgbGF0ZS4NCg0KYGBge3J9DQpmaWx0ZXIoZmxpZ2h0cywgYXJyX2RlbGF5ID4gMTIwICYgZGVwX2RlbGF5ID09IDApDQpgYGANCg0KKioxLjY6KiogV2VyZSBkZWxheWVkIGJ5IGF0IGxlYXN0IGFuIGhvdXIsIGJ1dCBtYWRlIHVwIG92ZXIgMzAgbWludXRlcyBpbiBmbGlnaHQuIFRoaXMgaXMgYSB0cmlja3kgb25lLiBEbyB5b3VyIGJlc3QuDQoNCmBgYHtyfQ0KZmlsdGVyKGZsaWdodHMsIGRlcF9kZWxheSA+PSA2MCAmIGFycl9kZWxheSA+PSAzMCkNCmBgYA0KDQoNCioqMS43OioqIERlcGFydGVkIGJldHdlZW4gbWlkbmlnaHQgYW5kIDZhbSAoaW5jbHVzaXZlKQ0KDQpgYGB7cn0NCmZpbHRlcihmbGlnaHRzLCBkZXBfdGltZSA+IDAwMDAgJiBkZXBfdGltZSA8IDYwMCkNCmBgYA0KDQoNCioqMjoqKiBBbm90aGVyIHVzZWZ1bCBkcGx5ciBmaWx0ZXJpbmcgaGVscGVyIGlzIGBiZXR3ZWVuKClgLiBXaGF0IGRvZXMgaXQgZG8/IENhbiB5b3UgdXNlIGl0IHRvIHNpbXBsaWZ5IHRoZSBjb2RlIG5lZWRlZCB0byBhbnN3ZXIgdGhlIHByZXZpb3VzIGNoYWxsZW5nZXM/DQoNCmJldHdlZW4oKSBpcyBhIHNob3J0Y3V0IGZvciBkZXRlcm1pbmluZyBpZiB2YWx1ZXMgaW4gYSBudW1lcmljIHZlY3RvciBmYWxsIGluIGEgc3BlY2lmaWMgcmFuZ2UuIFllcyB5b3UgY291bGQgdXNlIHRoaXMgdG8gbWFrZSBjb2RlcyBhYm92ZSBzaW1wbGllci4NCg0KKiozOioqIEhvdyBtYW55IGZsaWdodHMgaGF2ZSBhIG1pc3NpbmcgZGVwX3RpbWU/IFdoYXQgb3RoZXIgdmFyaWFibGVzIGFyZSBtaXNzaW5nPyBXaGF0IG1pZ2h0IHRoZXNlIHJvd3MgcmVwcmVzZW50Pw0KDQpgYGB7cn0NCg0KYGBgDQoNCioqNDoqKiBXaHkgaXMgYE5BIF4gMGAgbm90IG1pc3Npbmc/IFdoeSBpcyBgTkEgfCBUUlVFYCBub3QgbWlzc2luZz8gV2h5IGlzIGBGQUxTRSAmIE5BYCBub3QgbWlzc2luZz8gQ2FuIHlvdSBmaWd1cmUgb3V0IHRoZSBnZW5lcmFsIHJ1bGU/IChgTkEgKiAwYCBpcyBhIHRyaWNreSBjb3VudGVyZXhhbXBsZSEpDQoNCidOQSBeIDAnIGlzIG5vdCBtaXNzaW5nIGJlY2F1c2UgYW55IG51bWJlciBeIDAgaXMgZXF1YWwgdG8gb25lLiAnTkEgfCBUUlVFJyBpcyBub3QgbWlzc2luZyBiZWNhdXNlIE5BIGlzIGdvaW5nIHRvIHNob3cgRkFMU0UgYW5kIGNvbnNpZGVyaW5nIGFsbCB0aGluZ3MgYXJlIGVpdGhlciBUUlVFIG9yIEZBTFNFIGFuZCB0aGlzIHN0YXRlbWVudCBpbmNsdWRlcyBib3RoIGl0IGlzIG5vdCBtaXNzaW5nLiAnIEZBTFNFICYgTkEnIGlzIG5vdCBtaXNzaW5nIGJlY2F1c2UgYm90aCBlcXVhbCBGQUxTRS4NCg0KKipOb3RlOioqIEZvciBzb21lIGNvbnRleHQsIHNlZSBbdGhpcyB0aHJlYWRdKGh0dHBzOi8vYmxvZy5yZXZvbHV0aW9uYW5hbHl0aWNzLmNvbS8yMDE2LzA3L3VuZGVyc3RhbmRpbmctbmEtaW4tci5odG1sKQ0KDQoNCiMjIyA1LjMgQXJyYW5nZSB3aXRoIGBhcnJhbmdlKClgDQoNClRoaXMgY29kZSBjaHVuayBzaG93cyBob3cgdG8gdXNlIGFyYW5nZSgpIHRvIGNoYW5nZSBvcmRlciBvZiBjb2x1bW5zDQoNCmBgYHtyfQ0KYXJyYW5nZShmbGlnaHRzLCB5ZWFyLCBtb250aCwgZGF5KQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzaG93cyBob3cgdG8gdXNlIGRlc2MoKSB0byByZS1vcmRlciBhIGNvbHVtbiBieSBkZXNjZW5kaW5nIG9yZGVyLg0KDQpgYGB7cn0NCmFycmFuZ2UoZmxpZ2h0cywgZGVzYyhkZXBfZGVsYXkpKQ0KYGBgDQoNClRoaXMgY29kZSBjaHVuayBzaG93cyBtaXNzaW5nIHZhbHVlcyBzb3J0ZWQgYXQgdGhlIGVuZC4NCg0KYGBge3J9DQpkZiA8LSB0aWJibGUoeCA9IGMoNSwgMiwgTkEpKQ0KYGBgDQoNClRoaXMgaXMgcGFydCBvZiBhYm92ZS4NCg0KYGBge3J9DQphcnJhbmdlKGRmLCB4KQ0KYGBgDQoNCkFsc28sIHBhcnQgb2YgYWJvdmUuDQoNCmBgYHtyfQ0KYXJyYW5nZShkZiwgZGVzYyh4KSkNCmBgYA0KDQoNCiMjIyMgNS4zIFF1ZXN0aW9ucw0KDQoqKjE6KiogSG93IGNvdWxkIHlvdSB1c2UgYGFycmFuZ2UoKWAgdG8gc29ydCBhbGwgbWlzc2luZyB2YWx1ZXMgdG8gdGhlIHN0YXJ0PyAoSGludDogdXNlIGlzLm5hKCkpLiAqKk5vdGU6KiogVGhpcyBvbmUgc2hvdWxkIHN0aWxsIGhhdmUgdGhlIGVhcmxpZXN0IGRlcGFydHVyZSBkYXRlcyBhZnRlciB0aGUgYE5BYHMuICpIaW50OiogV2hhdCBkb2VzIGBkZXNjKClgIGRvPw0KDQpgYGB7cn0NCmFycmFuZ2UoZmxpZ2h0cywgZGVzYyh5ZWFyLCBtb250aCwgZGF5LCBpcy5uYSh5ZWFyLCBtb250aCxkYXkpKSkNCmBgYA0KDQoNCioqMjoqKiBTb3J0IGZsaWdodHMgdG8gZmluZCB0aGUgbW9zdCBkZWxheWVkIGZsaWdodHMuIEZpbmQgdGhlIGZsaWdodHMgdGhhdCBsZWZ0IGVhcmxpZXN0LiANCg0KVGhpcyBxdWVzdGlvbiBpcyBhc2tpbmcgZm9yIHRoZSBmbGlnaHRzIHRoYXQgd2VyZSBtb3N0IGRlbGF5ZWQgKGxlZnQgbGF0ZXN0IGFmdGVyIHNjaGVkdWxlZCBkZXBhcnR1cmUgdGltZSkgYW5kIGxlYXN0IGRlbGF5ZWQgKGxlZnQgYWhlYWQgb2Ygc2NoZWR1bGVkIHRpbWUpLg0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgRmxpZ2h0cyBtb3N0IGRlbGF5ZWQuDQoNCmBgYHtyfQ0KYXJyYW5nZShmbGlnaHRzLCBkZXNjKGRlcF9kZWxheSkpDQpgYGANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIGZsaWdodHMgbGVhc3QgZGVsYXllZC4NCg0KYGBge3J9DQphcnJhbmdlKGZsaWdodHMsIC1kZXNjKGRlcF9kZWxheSkpDQpgYGANCg0KDQoqKjM6KiogU29ydCBmbGlnaHRzIHRvIGZpbmQgdGhlIGZhc3Rlc3QgZmxpZ2h0cy4gSW50ZXJwcmV0IGZhc3Rlc3QgdG8gbWVhbiBzaG9ydGVzdCB0aW1lIGluIHRoZSBhaXIuDQoNCmBgYHtyfQ0KYXJyYW5nZShmbGlnaHRzLCAtZGVzYyhmbGlnaHQpKQ0KYGBgDQoNCipPcHRpb25hbCBjaGFsbGVuZ2U6KiBmYXN0ZXN0IGZsaWdodCBjb3VsZCByZWZlciB0byBmYXN0ZXN0IGFpciBzcGVlZC4gU3BlZWQgaXMgbWVhc3VyZWQgaW4gbWlsZXMgcGVyIGhvdXIgYnV0IHRpbWUgaXMgbWludXRlcy4gQXJyYW5nZSB0aGUgZGF0YSBieSBmYXN0ZXN0IGFpciBzcGVlZC4NCg0KDQoqKjQ6KiogV2hpY2ggZmxpZ2h0cyB0cmF2ZWxsZWQgdGhlIGxvbmdlc3Q/IFdoaWNoIHRyYXZlbGxlZCB0aGUgc2hvcnRlc3Q/DQoNCkZsaWdodHMgbG9uZ2VzdA0KDQpgYGB7cn0NCmFycmFuZ2UoZmxpZ2h0cywgZGVzYyhmbGlnaHQpKQ0KYGBgDQoNCnRyYXZlbGVkIHNob3J0ZXN0DQoNCmBgYHtyfQ0KYXJyYW5nZShmbGlnaHRzLCAtZGVzYyhmbGlnaHQpKQ0KYGBgDQoNCg0KIyMjIDUuNCBTZWxlY3QgY29sdW1ucyB3aXRoIGBzZWxlY3QoKWANCg0KVGhpcyBjb2RlIGNodW5rIHNob3dzIGhvdyB0byBvbmx5IHNob3cgY2VydGFpbiBjb2x1bW5zIGZyb20gZmxpZ2h0cy4NCg0KYGBge3J9DQpzZWxlY3QoZmxpZ2h0cywgeWVhciwgbW9udGgsIGRheSkNCmBgYA0KDQpEb2VzIHNhbWUgYXMgYWJvdmUuDQoNCmBgYHtyfQ0Kc2VsZWN0KGZsaWdodHMsIHllYXI6ZGF5KQ0KYGBgDQoNClRoaXMgY2h1bmsgc2hvd3MgaG93IHRvIG5vdCBzaG93IGNvbHVtbnMgZnJvbSBmbGlnaHRzLg0KDQpgYGB7cn0NCnNlbGVjdChmbGlnaHRzLCAtKHllYXI6ZGF5KSkNCmBgYA0KDQp0aGlzIGNvZGUgY2h1bmsgc2hvd3MgaG93IHRvIHJlbmFtZSB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KcmVuYW1lKGZsaWdodHMsIHRhaWxfbnVtID0gdGFpbG51bSkNCmBgYA0KDQpUaGlzIGNvZGUgY2h1bmsgc2hvd3MgaG93IHRvIG1vdmUgdmFyaWFibGVzIHRvIHRoZSBzdGFydCBvZiB0aGUgZGF0YWZyYW1lLg0KDQpgYGB7cn0NCnNlbGVjdChmbGlnaHRzLCB0aW1lX2hvdXIsIGFpcl90aW1lLCBldmVyeXRoaW5nKCkpDQpgYGANCg0KIyMjIyA1LjQgUXVlc3Rpb25zDQoNCioqMToqKiBCcmFpbnN0b3JtIGFzIG1hbnkgd2F5cyBhcyBwb3NzaWJsZSB0byBzZWxlY3QgYGRlcF90aW1lYCwgYGRlcF9kZWxheWAsIGBhcnJfdGltZWAsIGFuZCBgYXJyX2RlbGF5YCBmcm9tIGZsaWdodHMuIEZpbmQgYXQgbGVhc3QgdGhyZWUgd2F5cy4NCg0KYGBge3J9DQpzZWxlY3QoZmxpZ2h0cywgZGVwX3RpbWUsIGRlcF9kZWxheSwgYXJyX3RpbWUsIGFycl9kZWxheSkNCmBgYA0KDQpgYGB7cn0NCnNlbGVjdChmbGlnaHRzLCANCmBgYA0KDQoNCioqMjoqKiBXaGF0IGhhcHBlbnMgaWYgeW91IGluY2x1ZGUgdGhlIG5hbWUgb2YgYSB2YXJpYWJsZSBtdWx0aXBsZSB0aW1lcyBpbiBhIGBzZWxlY3QoKWAgY2FsbD8NCg0KYGBge3J9DQpzZWxlY3QoZmxpZ2h0cywgZGVwX3RpbWUsIGRlcF90aW1lLCBhcnJfdGltZSwgZGVwX3RpbWUpDQpgYGANCg0KTm90aGluZyBzaG93cyB1cCB3aGVuIHlvdSBydW4gdGhlIGNvZGUuDQoNCioqMzoqKiBXaGF0IGRvZXMgdGhlIGBvbmVfb2YoKWAgZnVuY3Rpb24gZG8/IFdoeSBtaWdodCBpdCBiZSBoZWxwZnVsIGluIGNvbmp1bmN0aW9uIHdpdGggdGhpcyB2ZWN0b3I/DQoNCmB2YXJzIDwtIGMoInllYXIiLCAibW9udGgiLCAiZGF5IiwgImRlcF9kZWxheSIsICJhcnJfZGVsYXkiKWANCg0Kb25lX29mKCkgbGV0cyB5b3Ugc2VsZWN0IHZhcmlhYmxlcyB1c2luZyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgdGhlaXIgbmFtZXMgaW5zdGVhZCBvZiBwdXR0aW5nIHRoZWlyIG5hbWVzIGludG8gdGhlIHNlbGVjdCgpIGNhbGwuIElmIHlvdSBhcmUgd2FudGluZyB0aGlzIHZlY3RvciwgeW91IGNhbiB1c2Ugb25lX29mKCkgd2l0aCBzb21lIG9mIHZhcmlhYmxlcyB0byBwdWxsIHVwIHRoZSB3aG9sZSB2ZWN0b3IuDQoNCioqNDoqKiBEb2VzIHRoZSByZXN1bHQgb2YgcnVubmluZyB0aGUgZm9sbG93aW5nIGNvZGUgc3VycHJpc2UgeW91PyBIb3cgZG8gdGhlIHNlbGVjdCBoZWxwZXJzIGRlYWwgd2l0aCBjYXNlIGJ5IGRlZmF1bHQ/IEhvdyBjYW4geW91IGNoYW5nZSB0aGF0IGRlZmF1bHQ/DQoNCnNlbGVjdChmbGlnaHRzLCBjb250YWlucygiVElNRSIpKQ0KDQpgYGB7cn0NCnNlbGVjdChmbGlnaHRzLCBjb250YWlucygiVElNRSIpKQ0KYGBgDQo=